home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-06-23 | 26.3 KB | 1,117 lines |
- // SVDrag.c
- //
- // Original version by Jon Lansdell and Nigel Humphreys.
- // 4.0 and 3.1 updates by Greg Sutton.
- // Drag Manager support by Chris White
- // ©Apple Computer Inc 1996, all rights reserved.
-
- #include "MSDrag.h"
- #include "MSWindow.h"
- #include "MSGlobals.h"
- #include "Offscreen.h"
-
- #include "DebugUtils.h"
-
-
- #include <Drag.h>
- #include <LowMem.h>
- #include <Errors.h>
- #include <Folders.h>
-
-
-
- static short gCaretOffset; // Caret drawn during a drag
-
-
-
- #pragma segment Drag
-
- //
- // InitDragHandlers creates the UPPs for the Drag Manager
- // callback routines _if_ the Drag Manager is available.
- //
- OSErr InitDragHandlers ( void )
- {
- OSErr theErr = noErr;
-
- if ( gHasDragManager )
- {
- gDragTrackingHandlerUPP = NewDragTrackingHandlerProc ( MyTrackingHandler );
- gDragReceiveHandlerUPP = NewDragReceiveHandlerProc ( MyReceiveHandler );
- }
-
- return theErr;
- }
-
-
-
- //
- // InstallDragHandlers attaches the tracking and receive handlers to
- // one of the application's windows.
- //
- OSErr InstallDragHandlers ( WindowRef theWindow )
- {
- OSErr theErr = noErr;
-
- if ( gHasDragManager )
- {
-
- theErr = InstallTrackingHandler ( gDragTrackingHandlerUPP, theWindow, nil );
-
- if ( theErr == noErr )
- {
- theErr = InstallReceiveHandler ( gDragReceiveHandlerUPP, theWindow, nil );
- if ( theErr )
- (void) RemoveTrackingHandler ( gDragTrackingHandlerUPP, theWindow );
- }
-
- }
-
- return theErr;
- }
-
-
-
- //
- // RemoveDragHandlers removes the tracking and receive handlers from
- // one of the application's windows (usually just prior to disposal).
- //
- void RemoveDragHandlers ( WindowRef theWindow )
- {
- if ( gHasDragManager )
- {
-
- RemoveReceiveHandler ( gDragReceiveHandlerUPP, theWindow );
- RemoveTrackingHandler ( gDragTrackingHandlerUPP, theWindow );
-
- }
-
- return;
- }
-
-
-
- Boolean IsDragInWindowContent ( DragReference theDrag, WindowRef theWindow )
- {
- Point localPt;
-
- GetDragMouse ( theDrag, &localPt, 0L );
- GlobalToLocal ( &localPt ); // Assumes theWindow is current port
-
- return PtInWindow ( localPt, theWindow );
- }
-
-
-
- Boolean PtInWindow ( Point localPt, WindowRef theWindow )
- {
- DPtr theDocument;
-
- theDocument = DPtrFromWindowPtr ( theWindow );
- return PtInDocument ( localPt, theDocument );
- }
-
-
-
- Boolean PtInDocument ( Point localPt, DPtr theDocument )
- {
- return PtInRect ( localPt, &(**(theDocument->theText)).viewRect );
- }
-
-
- Boolean CanAcceptDragItems ( DragReference theDrag, WindowPtr theWindow )
- {
- OSErr theErr;
- ItemReference theRef;
- Boolean bCanAccept = false;
- HFSFlavor currHFSFlavor;
- Size flavorDataSize;
- FlavorFlags currFlavorFlags;
- DPtr theDocument;
-
- theDocument = DPtrFromWindowPtr ( theWindow );
-
- if (theDocument->windowType == kOrdinaryWind)
- {
- theErr = GetDragItemReferenceNumber ( theDrag, 1, &theRef );
- if ( theErr == noErr )
- {
- // use GetFlavorFlags to check on flavor existence of TEXT data.
- theErr = GetFlavorFlags ( theDrag, theRef, 'TEXT', &currFlavorFlags );
- if ( theErr == noErr )
- bCanAccept = true;
- else
- {
- // check if the item is a file spec, and it contains TEXT
- flavorDataSize = sizeof ( HFSFlavor );
- theErr = GetFlavorData ( theDrag, theRef, flavorTypeHFS, &currHFSFlavor,
- &flavorDataSize, 0 );
-
- if ( theErr == noErr && currHFSFlavor.fileType == 'TEXT' )
- bCanAccept = true;
- }
- }
- }
-
- return (bCanAccept);
- }
-
-
-
- pascal OSErr MyTrackingHandler ( DragTrackingMessage theMessage, WindowPtr theWindow,
- void* handlerRefCon, DragReference theDrag )
- {
- #ifdef __MWERKS__
- #pragma unused(handlerRefCon)
- #endif
-
- static Boolean bHasAcceptableDrag;
- static Boolean bHasHilitedWindow;
- static Boolean bShowCaret;
-
- static long caretMovedTime;
- static short lastOffset, insertPosition;
-
- short theOffset;
- OSErr theErr = noErr;
- long theTime = TickCount ( );
- unsigned long theAttributes;
- RgnHandle tempRgn;
- DPtr theDocument, hitDocument;
-
-
- GetDragAttributes ( theDrag, &theAttributes );
- theDocument = DPtrFromWindowPtr ( theWindow );
-
- switch ( theMessage )
- {
- case dragTrackingEnterHandler:
- // Any initialization for this window handler.
-
- bHasAcceptableDrag = CanAcceptDragItems ( theDrag, theWindow );
-
- // Let the drag manager know if we can't accept this drag
- if ( !bHasAcceptableDrag )
- theErr = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
-
- caretMovedTime = theTime;
- gCaretOffset = lastOffset = -1;
- bShowCaret = true;
-
- bHasHilitedWindow = false;
-
- break;
-
- case dragTrackingInWindow:
- // Hiliting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window.
-
- if ( bHasAcceptableDrag )
- {
- // Check if the mouse is in a window's content region. Make an
- // exception if the window has yet to leave the source window,
- // since we don't want to hilite it in that stuation.
- Boolean bMouseInContent;
- Point theMouse;
-
- bMouseInContent = false;
-
- if ( theAttributes & dragHasLeftSenderWindow )
- {
- bMouseInContent = IsDragInWindowContent ( theDrag, theWindow );
- }
-
- // If the mouse is in a window and it isn't hilited...
- if ( bMouseInContent && !bHasHilitedWindow )
- {
- tempRgn = NewRgn ( );
- RectRgn ( tempRgn, &(**(theDocument->theText)).viewRect );
-
- // ...draw the hilight...
- if ( ShowDragHilite ( theDrag, tempRgn, true ) == noErr )
- // ... and remember it's now hilited
- bHasHilitedWindow = true;
-
- DisposeRgn ( tempRgn );
- }
-
-
- GetDragMouse ( theDrag, &theMouse, 0L );
- theOffset = HitTest ( theMouse, &hitDocument );
-
- if ( theDocument == hitDocument )
- {
-
- // Do not allow tracking through the selection in the
- // window that sourced the drag.
- if ( theAttributes & dragInsideSenderWindow )
- if ( IsOffsetInSelection ( theOffset, theDocument->theText ) )
- theOffset = -1;
-
-
-
- insertPosition = theOffset;
-
- // Reset flashing counter if the offset has moved. This makes the
- // caret blink only after the caret has stopped moving long enough.
- if ( theOffset != lastOffset )
- {
- caretMovedTime = theTime;
- bShowCaret = true;
- }
- lastOffset = theOffset;
-
-
- // Flash caret.
- if ( theTime - caretMovedTime > LMGetCaretTime ( ) )
- {
- bShowCaret = !bShowCaret;
- caretMovedTime = theTime;
- }
-
- if ( !bShowCaret )
- theOffset = -1;
-
- // If caret offset has changed, move caret on screen.
- if (theOffset != gCaretOffset)
- {
- if (gCaretOffset != -1)
- DrawCaret(gCaretOffset, theDocument->theText);
-
- if (theOffset != -1)
- DrawCaret(theOffset, theDocument->theText);
- }
-
- gCaretOffset = theOffset;
- }
- else
- {
- lastOffset = theOffset;
- insertPosition = -1;
- }
-
- }
- break;
-
- case dragTrackingLeaveWindow:
- // If the caret is on the screen, remove it.
- if (gCaretOffset != -1)
- {
- DrawCaret(gCaretOffset, theDocument->theText);
- gCaretOffset = -1;
- }
-
- // Remove any window hiliting here. If the mouse
- // is not in the window and it's hilited...
- if ( bHasHilitedWindow )
- // ...erase the hilight...
- if ( HideDragHilite ( theDrag ) == noErr )
- // ...remember that nothing is hilited
- bHasHilitedWindow = false;
- break;
-
- case dragTrackingLeaveHandler:
- break;
-
- default:
- theErr = paramErr;
- break;
- }
-
- return theErr;
- }
-
-
-
- Boolean IsOffsetInSelection ( short theOffset, TEHandle theTE )
- {
- return (theOffset >= (*theTE)->selStart && theOffset <= (*theTE)->selEnd);
- }
-
-
-
- //
- // DragIsNotInSourceWindow returns true if the drag in progress
- // is not in the same window it originated in. This is called by
- // the tracking and receive handlers.
- //
- static Boolean DragIsNotInSourceWindow ( DragReference theDrag )
- {
- DragAttributes currDragFlags;
-
- GetDragAttributes ( theDrag, &currDragFlags );
- return !(currDragFlags & dragInsideSenderWindow);
- }
-
-
-
- //
- // DragReceiver is called by the drag manager whenever an
- // item is dropped on one of the application's windows.
- //
- pascal OSErr MyReceiveHandler ( WindowPtr theWindow, void* handlerRefCon,
- DragReference theDrag )
- {
- #ifdef __MWERKS__
- #pragma unused(handlerRefCon)
- #endif
-
- Boolean bHaveData = false;
- Boolean bMove = false;
- OSErr theErr = noErr;
-
-
- unsigned short numItems;
- int i;
- unsigned long theAttributes;
- ItemReference theItem;
- Size textSize, styleSize;
- DPtr theDocument;
-
- short theOffset;
- Point thePoint = { 0, 0 };
-
- Ptr textData = nil;
- StScrpHandle styleHandle = nil;
-
- TEHandle tempTE = nil;
- Rect tempRect;
-
-
-
- RgnHandle tempRgn;
- Rect sourceRect, targetRect;
-
- tWindowOffscreen* theOffscreen = nil;
-
- if ( !(CanAcceptDragItems ( theDrag, theWindow ) && IsDragInWindowContent ( theDrag, theWindow )) )
- return dragNotAcceptedErr;
-
- theDocument = DPtrFromWindowPtr ( theWindow );
- GetDragAttributes ( theDrag, &theAttributes );
-
- // Get the location of the drop
- theErr = GetDragMouse ( theDrag, &thePoint, 0L );
- if ( theErr ) goto CleanupAndBail;
-
- GlobalToLocal ( &thePoint ); // Assumes theWindow is current port
- // Map the drop location to the text
- theOffset = TEGetOffset ( thePoint, theDocument->theText );
-
- // Don't allow a drop within the original selection
- if ( theAttributes & dragInsideSenderWindow )
- if ( IsOffsetInSelection ( theOffset, theDocument->theText ) )
- return dragNotAcceptedErr;
-
-
- // Is this drag copying or a moving the text?
- bMove = IsDragMoving ( theDrag );
-
- // First, gather all the text into a temp TE record, and then insert that into
- // the doucment. This approach makes it easy to handle things like text selection.
- SetRect ( &tempRect, 0, 0, 0, 0 );
- tempTE = TEStylNew ( &tempRect, &tempRect );
- theErr = MemError ( );
- if ( tempTE == nil || theErr ) goto CleanupAndBail;
-
- theErr = CountDragItems ( theDrag, &numItems );
- if ( theErr ) goto CleanupAndBail;
-
- for ( i = 1; i <= numItems; i++ )
- {
-
- theErr = GetDragItemReferenceNumber ( theDrag, i, &theItem );
- if ( theErr ) goto CleanupAndBail;
-
- theErr = GetFlavorDataSize ( theDrag, theItem, 'TEXT', &textSize );
- if ( theErr ) goto CleanupAndBail;
-
- textData = NewPtr ( textSize );
- theErr = MemError ( );
- if ( textData == nil || theErr ) goto CleanupAndBail;
-
- theErr = GetFlavorData ( theDrag, theItem, 'TEXT', textData, &textSize, 0L );
- if ( theErr ) goto CleanupAndBail;
-
-
- // Check for optional styl data for the TEXT.
- styleHandle = 0L;
- theErr = GetFlavorDataSize ( theDrag, theItem, 'styl', &styleSize );
- if ( !theErr )
- {
- styleHandle = (StScrpHandle) NewHandle ( styleSize );
- theErr = MemError ( );
- if ( styleHandle == nil || theErr ) goto CleanupAndBail;
-
- HLock ( (Handle) styleHandle );
- theErr = GetFlavorData ( theDrag, theItem, 'styl', *styleHandle, &styleSize, 0L );
- if ( theErr ) goto CleanupAndBail;
- HUnlock ( (Handle) styleHandle );
- }
-
- // Insert this drag item's text into the tempTE.
- TESetSelect ( 32767, 32767, tempTE );
- TEStylInsert ( textData, textSize, styleHandle, tempTE );
-
- DisposePtr ( textData );
- textData = nil;
- if ( styleHandle )
- {
- DisposeHandle ( (Handle) styleHandle );
- styleHandle = nil;
- }
-
- }
-
-
- // Pull the TEXT and styl data out of the tempTE handle.
- textData = NewPtr (textSize = (**tempTE).teLength );
- theErr = MemError ( );
- if ( textData == nil || theErr ) goto CleanupAndBail;
-
- BlockMoveData ( *(*tempTE)->hText, textData, textSize );
- TESetSelect ( 0, 32767, tempTE );
- styleHandle = TEGetStyleScrapHandle (tempTE );
- TEDispose ( tempTE );
- tempTE = nil;
-
-
- // Insert any text into the destination.
- if ( textSize != 0 )
- {
-
- // Get rid of the hilite/caret before inserting
- if ( theAttributes & dragHasLeftSenderWindow )
- HideDragHilite ( theDrag );
-
- if ( gCaretOffset != -1 )
- {
- DrawCaret ( gCaretOffset, theDocument->theText );
- gCaretOffset = -1;
- }
-
- // If the drag occurred completely within the same window and the window is not
- // frontmost, bring the window forward and update its contents before completing
- // the drag.
- if ( (theAttributes & dragInsideSenderWindow) && (theWindow != FrontWindow ( )) )
- {
- SelectWindow ( theWindow );
- DoUpdate ( theWindow );
- if (theDocument->windowType == kOrdinaryWind)
- TEActivate ( theDocument->theText );
- }
-
- // If the window is not active, must activate TE before inserting
- // text or the background hilite will not update correctly.
- if ( !IsWindowHilited ( theWindow ) )
- if (theDocument->windowType == kOrdinaryWind)
- TEActivate ( theDocument->theText );
-
- // Draw everything into offscreen pixmap.
- theOffscreen = DrawOffscreen ( theWindow );
- if ( theOffscreen )
- (*theDocument->theText)->inPort = (GrafPtr) theOffscreen->offscreenWorld;
-
- if ( bMove )
- {
- // Get the current hilite rgn for zooming (source)
- tempRgn = NewRgn ( );
- theErr = MemError ( );
- if ( theErr ) goto CleanupAndBail;
- GetSelectedTextRgn ( theDocument, tempRgn );
- sourceRect = (*tempRgn)->rgnBBox;
- LocalRectToGlobalRect ( &sourceRect, theWindow );
-
- // If this is a move operation, delete the old text.
- DeleteTextSelection ( theDocument->theText, &theOffset );
- }
-
- InsertTextAtOffset ( theOffset, textData, textSize, styleHandle, theDocument->theText );
-
- // If the text is moving (not copying) within the same window, provide a ZoomRects
- // from the source to the destination before revealing the reflowed text.
-
- if ( bMove )
- {
- // Get the current hilite rgn for zooming (target)
- GetSelectedTextRgn ( theDocument, tempRgn );
- targetRect = (*tempRgn)->rgnBBox;
- DisposeRgn ( tempRgn );
- tempRgn = nil;
- LocalRectToGlobalRect ( &targetRect, theWindow );
-
- ZoomRects ( &sourceRect, &targetRect, 12, zoomDecelerate );
- }
- }
-
- // Undo the TEActivate, if needed.
- if ( !IsWindowHilited ( theWindow ) )
- TEDeactivate ( theDocument->theText );
-
- // Show the offscreen bitmap.
- if ( theOffscreen )
- {
- theOffscreen = DrawOnscreen ( theOffscreen );
- (*theDocument->theText)->inPort = theWindow;
- }
-
- // Make the document dirty
- theDocument->dirty = true;
-
-
- CleanupAndBail:
-
-
- // All of these will be nil if no error occurred
- if ( textData )
- DisposePtr ( textData );
- if ( styleHandle )
- DisposeHandle ( (Handle) styleHandle );
- if ( tempTE )
- TEDispose ( tempTE );
- if ( tempRgn )
- DisposeRgn ( tempRgn );
-
- // Normally nil since DrawOnscreen calls DisposeOffscreen
- if ( theOffscreen )
- {
- DisposeOffscreen ( theOffscreen );
- (*theDocument->theText)->inPort = theWindow;
- }
-
-
- return theErr;
- }
-
-
-
- void DeleteTextSelection ( TEHandle theTE, short* theInsertPosition )
- {
- short selStart, selEnd;
-
- selStart = (*theTE)->selStart;
- selEnd = (*theTE)->selEnd;
- if ( WhiteSpaceAtOffset ( selStart - 1, theTE ) &&
- !WhiteSpaceAtOffset ( selStart, theTE ) &&
- !WhiteSpaceAtOffset ( selEnd - 1, theTE ) &&
- WhiteSpaceAtOffset ( selEnd, theTE ) )
- {
-
- if ( GetCharAtOffset ( selEnd, theTE ) == ' ' )
- (*theTE)->selEnd++;
- }
-
- if ( *theInsertPosition > selStart )
- *theInsertPosition -= ((*theTE)->selEnd - (*theTE)->selStart);
-
- TEDelete ( theTE );
-
- return;
- }
-
-
-
- static Boolean IsDragMoving ( DragReference theDrag )
- {
- DragAttributes theAttributes;
-
- GetDragAttributes ( theDrag, &theAttributes );
- return (theAttributes & dragInsideSenderWindow) && !IsDragWithOptionKey ( theDrag );
- }
-
-
-
- static Boolean IsDragWithOptionKey ( DragReference theDrag )
- {
- short mouseDownModifiers, mouseUpModifiers;
-
- GetDragModifiers ( theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers );
- return (mouseDownModifiers & optionKey) | (mouseUpModifiers & optionKey);
- }
-
-
-
- void OutlineRegion ( RgnHandle theRgn )
- {
- RgnHandle tempRgn;
-
- tempRgn = NewRgn ( );
- CopyRgn ( theRgn, tempRgn );
- InsetRgn ( tempRgn, 1, 1 );
- DiffRgn ( theRgn, tempRgn, theRgn );
- DisposeRgn ( tempRgn );
-
- return;
- }
-
-
-
- OSErr DoWindowContentDrag ( WindowPtr theWindow, EventRecord* theEvent )
- {
- OSErr theErr = noErr;
- DragReference theDrag = (unsigned long) nil;
- RgnHandle dragRgn = nil;
- Ptr dataPtr = nil;
- StScrpHandle styleHandle = nil;
- short dataSize;
-
- DPtr theDocument;
- Rect dragBounds;
- ItemReference theItem;
-
-
- // create a new drag
- theErr = NewDrag ( &theDrag );
- if ( theErr ) goto CleanupAndBail;
-
- // use the window ptr as item reference for the heck of it
- theItem = (ItemReference) theWindow;
-
- // add the data to the drag
- theDocument = DPtrFromWindowPtr ( theWindow );
- dataPtr = NewPtr ( 0L );
- theErr = GetSelectedText ( theDocument, dataPtr, &dataSize );
- if ( theErr || dataSize == 0 ) goto CleanupAndBail;
-
- theErr = AddDragItemFlavor ( theDrag, theItem, 'TEXT', dataPtr, dataSize, 0 );
- if ( theErr ) goto CleanupAndBail;
- DisposePtr ( dataPtr );
- dataPtr = nil;
-
-
- // Add style data
- styleHandle = TEGetStyleScrapHandle ( theDocument->theText );
- HLock ( (Handle) styleHandle );
- AddDragItemFlavor ( theDrag, theItem, 'styl', (Ptr) *styleHandle, GetHandleSize ( (Handle) styleHandle ), 0 );
- HUnlock ( (Handle) styleHandle );
- DisposeHandle ( (Handle) styleHandle );
- styleHandle = nil;
-
-
- // generate the bounds and region for the drag using the window's
- // content rectangle
- dragBounds = (**((WindowPeek) theWindow)->contRgn).rgnBBox;
- theErr = SetDragItemBounds(theDrag, theItem, &dragBounds);
- if ( theErr ) goto CleanupAndBail;
-
- dragRgn = NewRgn ( );
- GetSelectedTextRgn ( theDocument, dragRgn );
- LocalRgnToGlobalRgn ( dragRgn, nil );
- OutlineRegion ( dragRgn );
-
- // do the drag and clean up
- TrackDrag ( theDrag, theEvent, dragRgn );
-
-
- if ( DragIsNotInSourceWindow ( theDrag ) )
- {
- AEDesc dropLocation;
-
- // Get the drop location
- GetDropLocation ( theDrag, &dropLocation );
- if ( !IsDragWithOptionKey ( theDrag ) && DropLocationIsFinderTrash ( &dropLocation) )
- {
- // Delete the exact text. Don't call DeleteTextSelection
- TEDelete ( theDocument->theText );
- theDocument->dirty = true;
- }
-
- AEDisposeDesc ( &dropLocation );
- }
-
-
- CleanupAndBail:
-
- if ( theDrag )
- DisposeDrag(theDrag);
-
- if ( dragRgn )
- DisposeRgn ( dragRgn );
-
- // These should be nil
- if ( dataPtr )
- DisposePtr ( dataPtr );
- if ( styleHandle )
- DisposeHandle ( (Handle) styleHandle );
-
-
- return theErr;
- }
-
-
-
- void LocalRgnToGlobalRgn ( RgnHandle theRgn, WindowRef theWindow )
- {
- GrafPtr savePort;
- Point localPt, globalPt;
-
-
- if ( theWindow )
- {
- GetPort ( &savePort );
- SetPortWindowPort ( theWindow );
- }
-
- localPt = globalPt = *(Point*) &(*theRgn)->rgnBBox; // top left
- LocalToGlobal ( &globalPt );
- SubPt ( localPt, &globalPt );
- OffsetRgn ( theRgn, globalPt.h, globalPt.v );
-
- if ( theWindow )
- SetPort ( savePort );
-
- return;
- }
-
-
-
- void LocalRectToGlobalRect ( Rect* theRect, WindowRef theWindow )
- {
- GrafPtr savePort;
- Point localPt, globalPt;
-
-
- if ( theWindow )
- {
- GetPort ( &savePort );
- SetPortWindowPort ( theWindow );
- }
-
- localPt = globalPt = *(Point*) theRect; // top left
- LocalToGlobal ( &globalPt );
- SubPt ( localPt, &globalPt );
- OffsetRect ( theRect, globalPt.h, globalPt.v );
-
- if ( theWindow )
- SetPort ( savePort );
-
- return;
- }
-
-
-
-
- OSErr GetSelectedText ( DPtr theDocument, Ptr dataPtr, short* dataSize )
- {
- OSErr theErr;
- TEHandle teHandle = theDocument->theText;
-
- *dataSize = (**(teHandle)).selEnd - (**(teHandle)).selStart;
- if ( *dataSize )
- {
- SetPtrSize ( dataPtr, *dataSize );
- theErr = MemError ( );
- if ( theErr )
- return theErr;
- BlockMoveData ( *(**(teHandle)).hText + (**(teHandle)).selStart, dataPtr, *dataSize );
- }
-
- return noErr;
- }
-
-
-
- void GetSelectedTextRgn ( DPtr theDocument, RgnHandle dataRgn )
- {
- TEGetHiliteRgn ( dataRgn, theDocument->theText );
-
- return;
- }
-
-
-
- //
- // Does the user want to drag something? First, checks the click could
- // be a drag, then waits to see if the user starts to drag the text.
- //
- Boolean UserWantsToDrag ( WindowRef theWindow, Point globalPt )
- {
- Point localPt;
-
- localPt = globalPt;
- GlobalToLocal ( &localPt ); // Assumes theWindow is current port
- if ( PointInWindowSelection ( localPt, theWindow ) )
- return WaitMouseMoved ( globalPt );
-
- return false;
- }
-
-
-
- //
- // Returns true if the local point is in the window's current selection
- //
- Boolean PointInWindowSelection ( Point localPt, WindowRef theWindow )
- {
- Boolean bHit;
- RgnHandle tempRgn;
- DPtr theDocument;
-
- theDocument = DPtrFromWindowPtr ( theWindow );
- if ( !(PtInDocument ( localPt, theDocument )) )
- return false;
-
- tempRgn = NewRgn ( );
- GetSelectedTextRgn ( theDocument, tempRgn );
- bHit = PtInRgn ( localPt, tempRgn );
- DisposeRgn ( tempRgn );
-
- return bHit;
- }
-
-
-
- //
- // Given a point in global coordinates, HitTest returns a pointer to a
- // document structure if the point is inside a document window on the screen.
- // If the point is not inside a document window, HitTest return NULL in
- // theDoc. If the point is in a doument window and also in the viewRect of
- // the document's TextEdit field, HitTest also returns the offset into
- // the text that corresponds to that point. If the point is not in the text,
- // HitTest returns -1.
- //
- short HitTest(Point theLoc, DPtr* theDoc)
- {
- GrafPtr savePort;
- WindowPtr theWindow;
- short offset;
-
- *theDoc = 0L;
- offset = -1;
-
- if (FindWindow(theLoc, &theWindow) == inContent)
- {
- if ( Ours ( theWindow ) )
- {
- *theDoc = DPtrFromWindowPtr ( theWindow );
- GetPort ( &savePort );
- SetPort(theWindow);
- GlobalToLocal(&theLoc);
- SetPort ( savePort );
-
- if ((PtInRect(theLoc, &(**((**theDoc).theText)).viewRect)) &&
- (PtInRect(theLoc, &(**((**theDoc).theText)).destRect))) {
-
- offset = TEGetOffset(theLoc, (**theDoc).theText);
-
- if ((TEIsFrontOfLine(offset, (**theDoc).theText)) && (offset) &&
- ((*((**((**theDoc).theText)).hText))[offset - 1] != 0x0D) &&
- (TEGetPoint(offset - 1, (**theDoc).theText).h < theLoc.h)) {
- offset--;
- }
- }
- }
- }
-
- return(offset);
- }
-
-
-
- // TEIsFrontOfLine, given an offset and a TextEdit handle, returns true if
- // the given offset is at the beginning of a line start.
- short TEIsFrontOfLine ( short offset, TEHandle theTE )
-
- { short line = 0;
-
- if ((**theTE).teLength == 0)
- return(true);
-
- if (offset >= (**theTE).teLength)
- return( (*((**theTE).hText))[(**theTE).teLength - 1] == 0x0d );
-
- while ((**theTE).lineStarts[line] < offset)
- line++;
-
- return( (**theTE).lineStarts[line] == offset );
- }
-
-
-
- // TEGetLine, given an offset and a TextEdit handle, returns the line number
- // of the line that contains the offset.
- short TEGetLine ( short offset, TEHandle theTE )
-
- { short line = 0;
-
- if (offset > (**theTE).teLength)
- return((**theTE).nLines);
-
- while ((**theTE).lineStarts[line] < offset)
- line++;
-
- return(line);
- }
-
-
-
- //
- // DrawCaret draws a caret in a TextEdit field at the given offset. DrawCaret
- // expects the port to be set to the port that the TextEdit field is in.
- // DrawCaret inverts the image of the caret onto the screen.
- //
- void DrawCaret(short offset, TEHandle theTE)
-
- { Point theLoc;
- short theLine, lineHeight;
-
-
- // Get the coordinates and the line of the offset to draw the caret.
-
- theLoc = TEGetPoint(offset, theTE);
- theLine = TEGetLine(offset, theTE);
-
-
- // For some reason, TextEdit dosen't return the proper coordinates
- // of the last offset in the field if the last character in the record
- // is a carriage return. TEGetPoint returns a point that is one line
- // higher than expected. The following code fixes this problem.
- if ((offset == (**theTE).teLength) &&
- (*((**theTE).hText))[(**theTE).teLength - 1] == 0x0D) {
- theLoc.v += TEGetHeight(theLine, theLine, theTE);
- }
-
- // Always invert the caret when drawing.
- PenMode(patXor);
-
- //Get the height of the line that the offset points to.
- lineHeight = TEGetHeight(theLine, theLine, theTE);
-
- // Draw the appropriate caret image.
- MoveTo(theLoc.h - 1, theLoc.v - 1);
- Line(0, 1 - lineHeight);
-
- PenNormal();
- }
-
-
-
- char GetCharAtOffset(short offset, TEHandle theTE)
-
- {
- if (offset < 0)
- return(0x0D);
-
- return(((char *) *((**theTE).hText))[offset]);
- }
-
-
-
- Boolean WhiteSpace(char theChar)
-
- {
- return((theChar == ' ') || (theChar == 0x0D));
- }
-
-
-
- Boolean WhiteSpaceAtOffset(short offset, TEHandle theTE)
-
- { char theChar;
-
- if ((offset < 0) || (offset > (**theTE).teLength - 1))
- return(true);
-
- theChar = ((char *) *((**theTE).hText))[offset];
- return((theChar == ' ') || (theChar == 0x0D));
- }
-
-
-
- void InsertTextAtOffset(short offset, char *theBuf, long size, StScrpHandle theStyl, TEHandle theTE)
-
- {
- if (size == 0)
- return;
-
- // If inserting at the end of a word and the selection does not begin with
- // a space, insert a space before the insertion.
- if (!WhiteSpaceAtOffset(offset - 1, theTE) &&
- WhiteSpaceAtOffset(offset, theTE) &&
- !WhiteSpace(theBuf[0])) {
-
- TESetSelect(offset, offset, theTE);
- TEKey(' ', theTE);
- offset++;
- }
-
- // If inserting at the beginning of a word and the selection does not end
- // with a space, insert a space after the insertion.
- if ( WhiteSpaceAtOffset(offset - 1, theTE) &&
- !WhiteSpaceAtOffset(offset, theTE) &&
- !WhiteSpace(theBuf[size - 1])) {
-
- TESetSelect(offset, offset, theTE);
- TEKey(' ', theTE);
- }
-
- TESetSelect(offset, offset, theTE);
- TEStylInsert(theBuf, size, theStyl, theTE);
- TESetSelect(offset, offset + size, theTE);
-
- return;
- }
-
-
-
- //
- // DropLocationIsFinderTrash returns true if the given dropLocation
- // AEDesc is a descriptor of the Finder's Trash.
- //
- Boolean DropLocationIsFinderTrash ( AEDesc* dropLocation )
-
- { OSErr result;
- AEDesc dropSpec;
- FSSpecPtr theSpec;
- CInfoPBRec thePB;
- short trashVRefNum;
- long trashDirID;
-
-
-
- // Coerce the dropLocation descriptor to an FSSpec. If there's no dropLocation or
- // it can't be coerced into an FSSpec, then it couldn't have been the Trash.
- if ( (dropLocation->descriptorType != typeNull) &&
- (AECoerceDesc(dropLocation, typeFSS, &dropSpec) == noErr))
- {
-
- HLock(dropSpec.dataHandle);
- theSpec = (FSSpec *) *dropSpec.dataHandle;
-
- // Get the directory ID of the given dropLocation object.
- thePB.dirInfo.ioCompletion = 0L;
- thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name;
- thePB.dirInfo.ioVRefNum = theSpec->vRefNum;
- thePB.dirInfo.ioFDirIndex = 0;
- thePB.dirInfo.ioDrDirID = theSpec->parID;
-
- result = PBGetCatInfo(&thePB, false);
-
- HUnlock(dropSpec.dataHandle);
- AEDisposeDesc(&dropSpec);
-
- if ( result )
- return(false);
-
- // If the result is not a directory, it cannot be the Trash.
- if (!(thePB.dirInfo.ioFlAttrib & (1 << 4)))
- return(false);
-
- // Get information about the Trash folder.
- FindFolder ( theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID);
-
- // If the directory ID of the dropLocation object is the same as the directory ID
- // returned by FindFolder, then the drop must have occurred into the Trash.
- if ( thePB.dirInfo.ioDrDirID == trashDirID )
- return true;
- }
-
-
- return false;
- }
-
-